package com.appstore.action;

import java.io.File;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.Date;

import net.sf.json.JSONArray;

import org.apache.struts2.ServletActionContext;

import com.appstore.dao.IApplicationDao;
import com.appstore.dao.impl.ApplicationDaoImpl;
import com.appstore.exception.DaoException;
import com.appstore.model.Application;
import com.appstore.util.DateFormatUtil;
import com.appstore.util.FileCopy;
import com.appstore.util.FileNameUtil;
import com.opensymphony.xwork2.ActionSupport;

/**
 * ApplicationChangeAction offer some add, update and delete interface.
 * 
 * @author zhbhun
 * 
 */
public class ApplicationChangeAction extends ActionSupport {

	private IApplicationDao applicationDao;
	private Integer id;
	private Application app;

	public ApplicationChangeAction() {
		applicationDao = ApplicationDaoImpl.getApplicationDaoImpl();
	}

	/**
	 * add applicationS
	 * 
	 * @return view result
	 * @throws Exception
	 */
	public String addApplication() throws Exception {
		try {
			restoreApp(app);
			restoreIcon(app);
			restoreTwoDimentCode(app);
			restoreScreenshots(app);
			setAppSize(app);
			applicationDao.save(app);
		} catch (Exception e) {
			throw new Exception("add application error", e);
		}
		return "add_success";
	}

	/**
	 * update application
	 * 
	 * @return
	 * @throws Exception
	 */
	public String updateApplication() throws Exception {
		if (app == null) {
			return "change_fail";
		}
		try {
			Application temp = applicationDao.findbyId(app.getId());
			if (temp == null) {
				return "change_fail";
			}
			updateApp(app, temp);
			updateIcon(app, temp);
			updateTwodimentcode(app, temp);
			updateScreenshot(app, temp);
			setAppSize(app);
			app.setUpdatedTime(new Timestamp(new Date().getTime()));
			applicationDao.update(app);
		} catch (Exception e) {
			throw new Exception("update application error", e);
		}
		return "change_success";
	}

	public String deleteApplication() throws DaoException {
		Application app = applicationDao.findbyId(id);
		if (app == null) {
			return "delete_fail";
		} else {
			deleteFile(app.getDownloadUrl());
			deleteFile(app.getIcon());
			deleteFile(app.getTwoDimentCode());
			app.setScreenList(app.getScreenShot());
			for (int i = 0; i < app.getScreenList().size(); i++) {
				deleteFile(app.getScreenList().get(i));
			}
			applicationDao.delete(this.id);
		}
		return "delete_success";
	}

	private static void setAppSize(Application app) {
		File file = new File(ServletActionContext.getServletContext()
		        .getRealPath(app.getDownloadUrl()));
		if (file.exists()) {
			DecimalFormat decimalFormat = new DecimalFormat("#.0");
			app.setSize(decimalFormat.format(file.length() / 1024.0 / 1024.0)
			        + "M");
		} else {
			app.setSize("0M");
		}
	}

	private static void restoreApp(Application app) throws Exception {
		if (app.getDownloadCount() != null
		        && !("".equals(app.getDownloadUrl()))) {
			String storeName = app.getName() + "_"
			        + DateFormatUtil.noramlFormat(app.getCreatedTime())
			        + FileNameUtil.getExtention(app.getDownloadUrl());
			File src = new File(ServletActionContext.getServletContext()
			        .getRealPath(app.getDownloadUrl()));
			File tar = new File(ServletActionContext.getServletContext()
			        .getRealPath("/file/app") + "/" + storeName);
			FileCopy.copy(src, tar);
			src.delete();
			app.setDownloadUrl("/file/app/" + storeName);
		}
	}

	private static void restoreIcon(Application app) throws Exception {
		if (app.getIcon() != null && !("".equals(app.getIcon()))) {
			String storeName = app.getName() + "_"
			        + DateFormatUtil.noramlFormat(app.getCreatedTime())
			        + FileNameUtil.getExtention(app.getIcon());
			File src = new File(ServletActionContext.getServletContext()
			        .getRealPath(app.getIcon()));
			File tar = new File(ServletActionContext.getServletContext()
			        .getRealPath("/file/icon") + "/" + storeName);
			FileCopy.copy(src, tar);
			src.delete();
			app.setIcon("/file/icon/" + storeName);
		}
	}

	private static void restoreTwoDimentCode(Application app) throws Exception {
		if (app.getTwoDimentCode() != null
		        && !("".equals(app.getTwoDimentCode()))) {
			String storeName = app.getName() + "_"
			        + DateFormatUtil.noramlFormat(app.getCreatedTime())
			        + FileNameUtil.getExtention(app.getTwoDimentCode());
			File src = new File(ServletActionContext.getServletContext()
			        .getRealPath(app.getTwoDimentCode()));
			File tar = new File(ServletActionContext.getServletContext()
			        .getRealPath("/file/twodimentcode") + "/" + storeName);
			FileCopy.copy(src, tar);
			src.delete();
			app.setTwoDimentCode("/file/twodimentcode/" + storeName);
		}
	}

	private static void restoreScreenshots(Application app) throws Exception {
		JSONArray array = JSONArray.fromObject(app.getScreenShot());
		String storeName = app.getName() + "_"
		        + DateFormatUtil.noramlFormat(app.getCreatedTime()) + "_";
		for (int i = 0; i < array.size(); i++) {
			String filename = storeName + i
			        + FileNameUtil.getExtention(array.getString(i));
			File src = new File(ServletActionContext.getServletContext()
			        .getRealPath(array.getString(i)));
			File tar = new File(ServletActionContext.getServletContext()
			        .getRealPath("/file/scrennshot") + "/" + filename);
			FileCopy.copy(src, tar);
			src.delete();
			array.set(i, "/file/scrennshot/" + filename);
		}
		app.setScreenShot(array.toString());
	}

	private static void deleteFile(String path) {
		if ((path != null) && !("".equals(path))) {
			File file = new File(ServletActionContext.getServletContext()
			        .getRealPath(path));
			if (file.exists()) {
				file.delete();
			}
		}
	}

	private static void updateApp(Application newApp, Application oldApp)
	        throws Exception {
		if (newApp.getDownloadUrl() == null
		        || "".equals(newApp.getDownloadUrl())) {
			deleteFile(oldApp.getDownloadUrl());
			newApp.setDownloadUrl("");
		} else {
			if (!newApp.getDownloadUrl().equals(oldApp.getDownloadUrl())) {
				deleteFile(oldApp.getDownloadUrl());
				String storeName = newApp.getName() + "_"
				        + DateFormatUtil.noramlFormat(new Date())
				        + FileNameUtil.getExtention(newApp.getDownloadUrl());
				File src = new File(ServletActionContext.getServletContext()
				        .getRealPath(newApp.getDownloadUrl()));
				File tar = new File(ServletActionContext.getServletContext()
				        .getRealPath("/file/app") + "/" + storeName);
				if (src.exists()) {
					FileCopy.copy(src, tar);
					src.delete();
				}
				newApp.setDownloadUrl("/file/app/" + storeName);
			}
		}
	}

	private static void updateIcon(Application newApp, Application oldApp)
	        throws Exception {
		if (newApp.getIcon() == null || "".equals(newApp.getIcon())) {
			deleteFile(oldApp.getIcon());
			newApp.setIcon("");
		} else {
			if (!newApp.getIcon().equals(oldApp.getIcon())) {
				deleteFile(oldApp.getIcon());
				String storeName = newApp.getName() + "_"
				        + DateFormatUtil.noramlFormat(new Date())
				        + FileNameUtil.getExtention(newApp.getIcon());
				File src = new File(ServletActionContext.getServletContext()
				        .getRealPath(newApp.getIcon()));
				File tar = new File(ServletActionContext.getServletContext()
				        .getRealPath("/file/app") + "/" + storeName);
				if (src.exists()) {
					FileCopy.copy(src, tar);
					src.delete();
				}
				newApp.setIcon("/file/app/" + storeName);
			}
		}
	}

	private static void updateTwodimentcode(Application newApp,
	        Application oldApp) throws Exception {
		if (newApp.getTwoDimentCode() == null
		        || "".equals(newApp.getTwoDimentCode())) {
			deleteFile(oldApp.getTwoDimentCode());
			newApp.setTwoDimentCode("");
		} else {
			if (!newApp.getTwoDimentCode().equals(oldApp.getTwoDimentCode())) {
				deleteFile(oldApp.getTwoDimentCode());
				String storeName = newApp.getName() + "_"
				        + DateFormatUtil.noramlFormat(new Date())
				        + FileNameUtil.getExtention(newApp.getTwoDimentCode());
				File src = new File(ServletActionContext.getServletContext()
				        .getRealPath(newApp.getTwoDimentCode()));
				File tar = new File(ServletActionContext.getServletContext()
				        .getRealPath("/file/app") + "/" + storeName);
				if (src.exists()) {
					FileCopy.copy(src, tar);
					src.delete();
				}
				newApp.setTwoDimentCode("/file/app/" + storeName);
			}
		}
	}

	private static void updateScreenshot(Application newApp, Application oldApp)
	        throws Exception {
		String storeName = oldApp.getName() + "_"
		        + DateFormatUtil.noramlFormat(new Date()) + "_";
		JSONArray newScreenshots = JSONArray.fromObject(newApp.getScreenShot());
		JSONArray oldScreenshots = JSONArray.fromObject(oldApp.getScreenShot());
		for (int i = 0; i < newScreenshots.size(); i++) {
			if (!oldScreenshots.contains(newScreenshots.getString(i))) {
				String filename = storeName
				        + i
				        + FileNameUtil
				                .getExtention(newScreenshots.getString(i));
				File src = new File(ServletActionContext.getServletContext()
				        .getRealPath(newScreenshots.getString(i)));
				File tar = new File(ServletActionContext.getServletContext()
				        .getRealPath("/file/scrennshot") + "/" + filename);
				if (src.exists()) {
					FileCopy.copy(src, tar);
					src.delete();
				}
				newScreenshots.set(i, "/file/scrennshot/" + filename);
			}
		}
		for (int i = 0; i < oldScreenshots.size(); i++) {
			if (!newScreenshots.contains(oldScreenshots.getString(i))) {
				File file = new File(ServletActionContext.getServletContext()
				        .getRealPath(oldScreenshots.getString(i)));
				if (file.exists()) {
					file.delete();
				}
			}
		}
		newApp.setScreenShot(newScreenshots.toString());
	}

	public Application getApp() {
		return app;
	}

	public void setApp(Application app) {
		this.app = app;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

}
